package afk.biglog.gui;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.List;
import java.util.logging.*;
import java.util.prefs.*;

import javax.swing.*;

import afk.biglog.*;

public class MainViewAdapter implements ActionListener, ErrorHandler
{

	public JRootPane getRootPane()
	{
		return frame.getRootPane();
	}

	private static final String PREF_HEIGHT = "height";

	private static final String PREF_WIDTH = "width";

	private static final String PREF_CURRENT_DIR = "currentDir";

	private static final String M_CLOSE = "MENU_CLOSE";
	private static final String M_CLOSE_ALL = "MENU_CLOSE_ALL";
	private static final String M_COPY = "MENU_COPY";
	private static final String M_EXIT = "MENU_EXIT";
	private static final String M_FILTER = "MENU_FILTER";
	private static final String M_OPEN_NEW = "M_OPEN_NEW";

	private final Preferences preferences = Preferences.userNodeForPackage(MainViewAdapter.class);
	private final List<String> errorList = new ArrayList<String>();
	private final Map<JPanel, FileViewAdapter> fileViewAdapters = Collections.synchronizedMap(new HashMap<JPanel, FileViewAdapter>());
	private final JFrame frame = new JFrame();
	private final Logger log = Logger.getLogger(MainViewAdapter.class.getName());

	private BigLogViewApplication app;
	private JPanel bottom;
	private JTabbedPane editorPane;
	private JPanel mainPanel;
	private JLabel statusLabel;
	private JPanel top;

	@Override
	public void actionPerformed(final ActionEvent e)
	{
		if (app == null)
		{
			log.warning("No APP for " + e);
			return;
		}

		if (e != null)
			if (e.getActionCommand() == M_OPEN_NEW)
				showOpenFileDialog();
			else
				if (e.getActionCommand() == M_CLOSE)
					closeCurrent();
				else
					if (e.getActionCommand() == M_CLOSE_ALL)
						closeAll();
	}

	/* (non-Javadoc)
	 * @see afk.biglog.gui.ErrorHandler#addError(java.lang.String, java.lang.Throwable)
	 */
	@Override
	public void addError(final String string, final Throwable e)
	{
		statusLabel.setText(string + " " + e.getMessage());
		errorList.add(string + " " + e.getMessage());
	}

	public void addFileViewer(final FileViewAdapter guiAdapter)
	{
		editorPane.add(guiAdapter.getMainPanel(), guiAdapter.getFile().getName());
		fileViewAdapters.put(guiAdapter.getMainPanel(), guiAdapter);
	}

	public void init()
	{

		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainPanel = new JPanel(new BorderLayout());
		editorPane = new JTabbedPane();
		editorPane.setTransferHandler(new FileAdderTransferhandler(app));
		bottom = new JPanel();
		statusLabel = new JLabel();
		bottom.add(statusLabel);
		top = new JPanel();
		frame.setContentPane(mainPanel);
		mainPanel.add(editorPane, BorderLayout.CENTER);
		mainPanel.add(bottom, BorderLayout.SOUTH);
		mainPanel.add(top, BorderLayout.NORTH);
		frame.setPreferredSize(selectPreferedSize());
		frame.setMinimumSize(selectPreferedSize());
		frame.setMaximumSize(selectPreferedSize());
		frame.setJMenuBar(createMenu());
		frame.setTitle("BiFiVi - Big File Viewer. (Name still sux)");
	}

	public void register(final BigLogViewApplication app)
	{
		this.app = app;
	}

	public void show()
	{
		frame.setVisible(true);
	}

	private void closeFileViewerAdapter(final FileViewAdapter remove)
	{
		editorPane.remove(remove.getMainPanel());
		remove.close();
	}

	private void closeAll()
	{
		synchronized (fileViewAdapters)
		{
			for (final Entry<JPanel, FileViewAdapter> entry : fileViewAdapters.entrySet())
				closeFileViewerAdapter(entry.getValue());
			fileViewAdapters.clear();
		}
	}

	private void closeCurrent()
	{
		final Component selectedComponent = editorPane.getSelectedComponent();
		final FileViewAdapter remove = fileViewAdapters.remove(selectedComponent);
		closeFileViewerAdapter(remove);
	}

	private JMenu createAboutMenu()
	{
		final JMenu menu = new JMenu("About");
		menu.setMnemonic(KeyEvent.VK_DEAD_TILDE);
		menu.add(new JMenuItem("Free to use"));
		menu.add(new JMenuItem("Under every term"));
		menu.add(new JMenuItem("Written by Axel.evil@gmail.com"));
		menu.addSeparator();
		menu.add(new JMenuItem("Donate"));

		return menu;
	}

	private JMenu createEditMenu()
	{
		final JMenu menu = new JMenu("Edit");
		menu.setMnemonic(KeyEvent.VK_E);
		menu.add(createMenuItem("Copy", KeyEvent.VK_C, M_COPY));
		menu.add(createMenuItem("Filter", KeyEvent.VK_F, M_FILTER));
		return menu;
	}

	private JMenu createFileMenu()
	{
		final JMenu menu = new JMenu("File");
		menu.setMnemonic(KeyEvent.VK_F);

		menu.add(createMenuItem("Open", KeyEvent.VK_O, M_OPEN_NEW));
		menu.add(createMenuItem("Close", KeyEvent.VK_C, M_CLOSE));
		menu.add(createMenuItem("Close All", KeyEvent.VK_A, M_CLOSE_ALL));

		menu.addSeparator();
		menu.add(createMenuItem("Exit", KeyEvent.VK_ALT + KeyEvent.VK_F4, M_EXIT));
		return menu;
	}

	private JMenuBar createMenu()
	{
		final JMenuBar menuBar = new JMenuBar();
		menuBar.add(createFileMenu());
		menuBar.add(createEditMenu());
		menuBar.add(createAboutMenu());
		return menuBar;
	}

	private JMenuItem createMenuItem(final String name, final int mnemnonic, final String command)
	{
		final JMenuItem item = new JMenuItem(name);
		item.setMnemonic(mnemnonic);
		item.setActionCommand(command);
		registerAsListener(item);
		return item;
	}

	private String getCurrentDir()
	{
		return preferences.get(PREF_CURRENT_DIR, System.getProperty("user.dir"));
	}

	private void registerAsListener(final Component... components)
	{
		for (final Component iterable_element : components)
			if (iterable_element instanceof JMenuItem)
				((JMenuItem) iterable_element).addActionListener(this);
	}

	private Dimension selectPreferedSize()
	{
		final int width = preferences.getInt(PREF_WIDTH, 600);
		final int height = preferences.getInt(PREF_HEIGHT, 300);
		return new Dimension(width, height);
	}

	private void setCurrentDir(final String parent)
	{
		preferences.put(PREF_CURRENT_DIR, parent);
	}

	private void showOpenFileDialog()
	{
		final JFileChooser chooser = new JFileChooser(getCurrentDir());
		chooser.showOpenDialog(frame);
		if (chooser.getSelectedFile() != null)
		{
			setCurrentDir(chooser.getSelectedFile().getParent());
			SwingUtilities.invokeLater(new Runnable()
			{

				@Override
				public void run()
				{
					app.openFile(chooser.getSelectedFile());
				}
			});
		}
		else
			if (chooser.getSelectedFiles() != null)
				for (final File file : chooser.getSelectedFiles())
				{
					setCurrentDir(file.getParent());
					app.openFile(file);
				}
	}
}
